#include "aibase.h"

////////////////////////////////
//
//IMPORTANT! Write the name of your player
//
#define NAMEPLAYER BasicGamer
//
////////////////////////////////

namespace NAMEPLAYER {                  //Do not change this line

  // IMPORTANT! Do not use global variables.

  //////////////////////////////////////////////////
  //
  //   However, it is okay to define const variables, functions,
  // typedefs, or structs/classes. Please do it here:
  //   



  //
  //
  //////////////////////////////////////////////////


  //////////////////////////////////////////////////
  //
  //  You must implement the function 'fes_torn'
  //

  struct AIstruct: public AIbase {      //Do not change this line
#include "initializer.h"  //Do not change this line


#define DIRECCIONES 8
#define DISTANCIA_SEGURIDAD 100
#define INFINITO 99999
    
    typedef struct {
	int x;
	int y;
    }Punto;
    
    
    int direccion(Punto& pos_pag, Punto& pos_siguiente) {
    	int x, y;
	x = pos_siguiente.x - pos_pag.x;
	y = pos_siguiente.y - pos_pag.y;
	if (x == 0 and y == -1) return NORD;
	if (x == 1 and y == -1) return NE;
	if (x == 1 and y == 0) return EST;
	if (x == 1 and y == 1) return SE;
	if (x == 0 and y == 1) return SUD;
	if (x == -1 and y == 1) return SO;
	if (x == -1 and y == 0) return OEST;
	if (x == -1 and y == -1) return NO;
	return 1+random(8);
    }
    
    
    void alrededores(Punto& original, vector<Punto>& vec){
	vec[0].y = vec[1].y = vec[2].y = original.y - 1; 	//NORTE.i-1=NE.i-1=NO.i-1
	vec[0].x = vec[4].x = original.x;			//NORTE.j = SUD.j
	vec[1].x = vec[2].x = vec[3].x = original.x + 1;	//NE.j+1 = EST.j+1 = SE.j+1
	vec[5].x = vec[6].x = vec[7].x = original.x - 1;	//SO.j-1 = OEST.j-1 = NO.j-1
	vec[3].y = vec[4].y = vec[5].y = original.y + 1;        //SE.i+1 = SUD.i+1 = SO.i+1
	vec[6].y = vec[2].y = original.y;			//OEST.i = EST.i
    }
    
    bool ocupada(Punto& casilla) {
	return existeix(casilla.y, casilla.x);
    }
    
    void inicia_rebotes(vector<int>& rebotes) {
	for (int i = 0; i < DIRECCIONES; ++i) rebotes[i] = ((i + 2)%8) + 1;
    }
    
    void huir(int rob, Punto& pos, Punto& robotCerca,vector<Punto>& alrededor,vector<int>& rebotes) {
	int n = alrededor.size();
	int distancia_actual = distancia(pos,robotCerca);
	bool mas_lejos = false;
	int i;
	for (i = 0; i < n and not mas_lejos; ++i) {
		if(distancia_actual < distancia(alrededor[i],robotCerca)) {
			mas_lejos = true;
		}
	}
	if (mas_lejos) moveTo(rob,pos,alrededor[i],rebotes);
	else {
		Punto aux;
		aux.x = pos.x;
		aux.y = pos.y+1;
		moveTo(rob,pos,aux,rebotes);
	}
    }


    void dar_paso(int rob, Punto& pos, vector<Punto>& alrededor, vector<int>& rebotes,  vector<int>& e2, vector<int>& e3, vector<int>& e4,vector<int>& p2,vector<int>& p3,vector<int>& p4) {
      int n = alrededor.size();
      for (int i = 0; i < n; ++i) {  
	  int col = color(alrededor[i].y,alrededor[i].x);
	  bool casilla_ocupada = ocupada(alrededor[i]);
	  Punto rmc = robot_mas_cerca(pos,e2,e3,e4,p2,p3,p4); 
	 // cerr << "Esta es la distancia que hay : " << distancia(pos,rmc) << endl;
	  if(distancia(pos, rmc) > DISTANCIA_SEGURIDAD) {
	      if (col != 1) {
		  if ((col == 0 or col > 1) and !casilla_ocupada) { //si via libre
		    ordena(rob,direccion(pos,alrededor[i]));
		    return;
		  }
		  else if(!casilla_ocupada){ //mejorar este caso
		    bool movimiento_correcto = ordena(rob,rebotes[direccion(pos,alrededor[i]) - 1]);
		    if (!movimiento_correcto) ordena(rob, 3+random(4)); //buen resultado
		    return;
		  }
	      }
	  } 
	  else huir(rob,pos,rmc,alrededor,rebotes);
      }
      if (torn_actual() < 150) ordena(rob,3+random(4));
      else ordena(rob,6+random(3));
    }
    int distancia(Punto& p1,Punto& p2) {
	if ((p2.y == -1 and p2.x == -1) or (p1.x == -1 and p1.y == -1)) return DISTANCIA_SEGURIDAD + 1; 
	return ((p2.x - p1.x)*(p2.x - p1.x)) + ((p2.y - p1.y)*(p2.y - p1.y));
    }

    Punto robot_mas_cerca(Punto& rob_pos, vector<int>& e2, vector<int>& e3, vector<int>& e4,
					  vector<int>& p2, vector<int>& p3, vector<int>& p4) {
	Punto a;
	a.x = -1;
	a.y = -1;
	Punto rob_cerca = a;
	int distancia_min = INFINITO;
	int n2, n3, n4, np2, np3, np4;
	n2 = e2.size();
	n3 = e3.size();
	n4 = e4.size();
	np2 = p2.size();
	np3 = p3.size();
	np4 = p4.size();
	for (int i = 0; i < n2; ++i) {
	   	if (e2[i] != -1) {
			a.x = robot(e2[i]).j;
			a.y = robot(e2[i]).i;
			if (distancia(a,rob_pos) < distancia_min){
				distancia_min = distancia(a,rob_pos);
				rob_cerca = a;
			}
		}
	}
	for (int i = 0; i < n3; ++i) {
		if (e3[i] != -1) {
			a.x = robot(e3[i]).j;
			a.y = robot(e3[i]).i;
			if (distancia(a,rob_pos) < distancia_min){
				distancia_min = distancia(a,rob_pos);
				rob_cerca = a;
			}
		}
	}
	for (int i = 0; i < n4; ++i) {
	   	if (e4[i] != -1) {
			a.x = robot(e4[i]).j;
			a.y = robot(e4[i]).i;
			if (distancia(a,rob_pos) < distancia_min){
				distancia_min = distancia(a,rob_pos);
				rob_cerca = a;
			}
		}
	}
	for (int i = 0; i < np2; ++i) {
	   	if (p2[i] != -1) {
	    		a.x = robot(p2[i]).j;
			a.y = robot(p2[i]).i;
			if (distancia(a,rob_pos) < distancia_min){
				distancia_min = distancia(a,rob_pos);
				rob_cerca = a;
			}
		}
	}
	for (int i = 0; i < np3; ++i) {
	   	if (p3[i] != -1) {
			a.x = robot(p3[i]).j;
			a.y = robot(p3[i]).i;
			if (distancia(a,rob_pos) < distancia_min){
				distancia_min = distancia(a,rob_pos);
				rob_cerca = a;
			}
		}
	}
	for (int i = 0; i < np4; ++i) {
	   	if (p4[i] != -1) {
			a.x = robot(p4[i]).j;
			a.y = robot(p4[i]).i;
			if (distancia(a,rob_pos) < distancia_min){
				distancia_min = distancia(a,rob_pos);
				rob_cerca = a;
			}
		}
	}
	return rob_cerca;
    }

    void moveTo(int idrobot, Punto& origen, Punto& destino, vector<int> reb) {
	Punto pos_rob;
	pos_rob.x = origen.x;
	pos_rob.y = origen.y;
	Punto pos_siguiente;
	pos_siguiente.x = pos_rob.x;
	pos_siguiente.y = pos_rob.y;
	if (destino.x > pos_siguiente.x) ++pos_siguiente.x;
	else if (destino.x < pos_siguiente.x) --pos_siguiente.x;
	if (destino.y > pos_siguiente.y) ++pos_siguiente.y;
	else if (destino.y < pos_siguiente.y) --pos_siguiente.y;
	int direc = direccion(pos_rob, pos_siguiente);
	bool moveOK = ordena(idrobot, direc);
	if(!moveOK) {
	  ordena(idrobot, reb[direc-1]);
	}
	return;
    }
    
    void fes_torn() {
	vector<int> rebotes(DIRECCIONES);

	inicia_rebotes(rebotes);

	vector<int> pag = pagesos(1);
	vector<int> cav = cavallers(1);
	int size_pag = pag.size();
	int size_cav = cav.size();
	
	vector<int> equipo2_caballeros = cavallers(2);
	vector<int> equipo3_caballeros = cavallers(3);
	vector<int> equipo4_caballeros = cavallers(4);

	vector<int> equipo2_pageses = pagesos(2);
	vector<int> equipo3_pageses = pagesos(3);
	vector<int> equipo4_pageses = pagesos(4);
	
	for (int i = 0; i < size_pag; ++i) {
	    Punto pos_pag;
	    pos_pag.x = robot(pag[i]).j;
	    pos_pag.y = robot(pag[i]).i;  
	    vector<Punto>alrededor_pag(DIRECCIONES);
	    alrededores(pos_pag,alrededor_pag);
	    dar_paso(pag[i],pos_pag,alrededor_pag,rebotes, equipo2_caballeros,equipo3_caballeros,equipo4_caballeros,
					     equipo2_pageses, equipo3_pageses, equipo4_pageses);
	}

	
	
	for (int i = 0; i < size_cav; ++i) {
	  Punto pos_cav;
	  pos_cav.x = robot(cav[i]).j;
	  pos_cav.y = robot(cav[i]).i;
	  vector<Punto>alrededor_cav(DIRECCIONES);
	  alrededores(pos_cav,alrededor_cav);
	  Punto pos_cav2;
	  pos_cav2 = robot_mas_cerca(pos_cav,equipo2_caballeros,equipo3_caballeros,equipo4_caballeros,
					     equipo2_pageses, equipo3_pageses, equipo4_pageses);
	  moveTo(cav[i], pos_cav, pos_cav2,rebotes);
	}
	  
    }

  };

  //
  //
  //////////////////////////////////////////////////  



  AIstruct::Static_Initializer init;    //Do not change this line
};                                      //Do not change this line
